#include "Combatant.h"
#include "CombatResponse.h"

namespace Combat
{
	Combatant::Combatant( Entity* entity ) : m_parent(entity)
	{
	}

	Subject<int>& Combatant::Health()
	{
		return m_health;
	}
	Subject<int>& Combatant::PhysicalDamage()
	{
		return m_physicalDamage;
	}
	Subject<Maths::Vector3D>& Combatant::Position()
	{
		return m_position;
	}
	Subject<int>& Combatant::SpecialDamage()
	{
		return m_specialDamage;
	}

	IEffect::Map_t& Combatant::Effects()
	{
		return m_effects;
	}
	void Combatant::RemoveEffectsOfType( HashedString type )
	{
		m_effects[type].clear();
	}

	void Combatant::ActivatePreAttackEffects( Response& response )
	{
		for (IEffect::Map_t::iterator mit = m_effects.begin(); mit != m_effects.end(); ++mit)
		{
			for (IEffect::List_t::iterator lit = mit->second.begin(); lit != mit->second.end(); ++lit)
			{
				(*lit)->OnPreAttack( response );
			}
		}
	}
	void Combatant::ActivatePreDefenseEffects( Response& response )
	{
		for (IEffect::Map_t::iterator mit = m_effects.begin(); mit != m_effects.end(); ++mit)
		{
			for (IEffect::List_t::iterator lit = mit->second.begin(); lit != mit->second.end(); ++lit)
			{
				(*lit)->OnPreDefend( response );
			}
		}
	}
	void Combatant::ActivatePostDefenseEffects( Response& response )
	{
		for (IEffect::Map_t::iterator mit = m_effects.begin(); mit != m_effects.end(); ++mit)
		{
			for (IEffect::List_t::iterator lit = mit->second.begin(); lit != mit->second.end(); ++lit)
			{
				(*lit)->OnPostDefend( response );
			}
		}
	}
	void Combatant::ActivatePostAttackEffects( Response& response )
	{
		for (IEffect::Map_t::iterator mit = m_effects.begin(); mit != m_effects.end(); ++mit)
		{
			for (IEffect::List_t::iterator lit = mit->second.begin(); lit != mit->second.end(); ++lit)
			{
				(*lit)->OnPostAttack( response );
			}
		}
	}

	IAbility::Vector_t& Combatant::Abilities()
	{
		return m_abilities;
	}

	void Combatant::HandleResponse( Response& response )
	{
		m_health -= response.physicalDamage;
		m_health -= response.specialDamage;
		m_health -= response.trueDamage;
		
		for (IEffect::List_t::iterator it = response.effects.begin(); it != response.effects.end(); ++it)
		{
			m_effects[(*it)->Type()].push_back((*it));
		}
	}
	Entity* Combatant::Parent()
	{
		return m_parent;
	}
}